package cn.tworice.admin.web;

import cn.tworice.admin.service.LogService;
import cn.tworice.admin.service.LoginService;
import cn.tworice.admin.service.SystemService;
import cn.tworice.common.entity.Admin;
import cn.tworice.common.entity.Role;
import cn.tworice.common.entity.dto.ResourcesDto;
import cn.tworice.common.entity.dto.SendMailDto;
import cn.tworice.common.utils.AgingMap;
import cn.tworice.common.utils.MailUtil;
import cn.tworice.common.utils.TokenUtil;
import cn.tworice.common.vo.RequestResult;
import cn.tworice.common.vo.StatusCode;
import com.wf.captcha.ArithmeticCaptcha;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;


/**
 * 登录注册操作及登录页数据展示
 *
 * @author 二饭
 */

@RestController
@RequestMapping("admin/login")
@Slf4j
@CrossOrigin
public class LoginController {

    @Autowired
    LoginService loginService;

    @Autowired
    private LogService logService;

    @Autowired
    private SystemService systemService;

    @Autowired
    private AgingMap<String,Object> agingMap;

    @Autowired
    private MailUtil mailUtil;

    /**
     * 验证码时效
     */
    @Value("${admin.login.captchaAging}")
    private long captchaAging;

    /**
     * 读取环境变量或配置文件中的超级管理员账号密码
     **/
    @Value("${admin.login.root}")
    private String root;

    /**
     * @param username 用户名
     * @param password 密码
     * @param verCode 验证码
     * @param key 验证码Key
     * @return  400-验证码错误
     *          200-登录成功
     *          400-登录失败，账号密码错误或账户被停用
     */
    @ApiOperation("登录")
    @PostMapping()
    public RequestResult login(String username, String password,String verCode,String key) {
        RequestResult result = new RequestResult();
        // 判断验证码
        if (verCode==null || !agingMap.exist(key,verCode)) {
            logService.addLoginLog(username, password, 0); // 写入日志
            result.setStatus(new StatusCode(400,"验证码错误或已超时"));
            return result;
        }

        // 用户信息
        Admin admin=null;
        // Token
        String token=null;

        // 判断是否为超级管理员
        if((username+"-"+password).equals(root)){
            admin= new Admin();
            admin.setId("1");
            admin.setNickName("超级管理员");
            result.setStatus(new StatusCode(200, "登录成功"));
            // 登录成功生成Token
            token = TokenUtil.getAdminToken(admin);
            // 获取权限资源
            List<ResourcesDto> resources = loginService.getResources(admin.getId());

            // 构建返回客户端内容
            result.appendData("token", token);
            result.appendData("admin", admin);
            result.appendData("resources", resources);

            List<Role> roles = new ArrayList<>();
            Role role = new Role();
            role.setId(0);
            role.setRoleName("超级管理");
            roles.add(role);
            result.appendData("roles", roles);
        }else {

            // 判断账号密码是否正确
            admin = loginService.checkLogin(username, password);
            if (admin == null) {
                result.setStatus(new StatusCode(400, "用户名或密码有误"));
                logService.addLoginLog(username, password, 0); // 写入日志
            } else {
                // 判断账号是否被停用
                if (admin.getStatus() == -1) {
                    result.setStatus(new StatusCode(400, "账户已被停用"));
                    logService.addLoginLog(username, password, 0);
                } else {
                    logService.addLoginLog(username, password, 1); // 写入日志
                    result.setStatus(new StatusCode(200, "登录成功"));
                    // 登录成功生成Token
                    token = TokenUtil.getAdminToken(admin);



                    // 登录成功获取该用户的权限资源
                    List<ResourcesDto> resources = loginService.getResourceByRole(admin.getId());
                    // 获取拥有的权限
                    List<Role> roles = loginService.getRolesById(admin.getId());

                    // 构建返回客户端内容
                    result.appendData("token", token);
                    result.appendData("admin", admin);
                    result.appendData("resources", resources);
                    result.appendData("roles", roles);
                }
            }
        }

        // 记录在线用户
        if(admin!=null){
            systemService.addAdminMap(admin.getId(),token);
        }

        // 该Key已经被使用，不再有效
        agingMap.remove(key);
        return result;
    }

    /**
     * 2022年5月13日 将原Redis替换为AgingMap，并添加切换验证码时使原验证码失效
     * @param code 用户切换验证码时删除原验证码
     * Author 二饭
     */
    @GetMapping("captcha")
    @ApiOperation("获取验证码图片")
    public RequestResult captcha(String code){
        if(code!=null){
            // 删除原验证码
            agingMap.remove(code);
        }

        RequestResult result = new RequestResult();

        ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 48);
        captcha.setLen(3);  // 几位数运算，默认是两位
//        captcha.getArithmeticString();  // 获取运算的公式：3+2=?
//        captcha.text();  // 获取运算的结果：5

        // 生成UUID作为Key 将验证码的结果存在AgingMap
        String key = UUID.randomUUID().toString().replaceAll("-", "");
        if(agingMap.put(key, captcha.text(), captchaAging)==null){
            result.setStatus(new StatusCode(204,"验证码请求频繁，请稍后再试"));
        }else {
            // 构建返回客户端数据对象
            result.setStatus(new StatusCode(200,"请求成功"));
            result.appendData("captcha",captcha.toBase64());
            result.appendData("key", key);
        }
        return result;
    }

    /**
     * 发送邮箱验证码
     * @author 二饭[tworice@sina.cn][2022/1/22 18:26]
     */
    @GetMapping("regCaptcha")
    public RequestResult regCaptcha(String email){
        RequestResult result = new RequestResult();
        // 生成四位数验证码
        StringBuilder verCode=new StringBuilder();
        for (int i = 0; i <4 ; i++) {
            verCode.append(new Random().nextInt(10));
        }

        String key = UUID.randomUUID().toString().replaceAll("-", "");
        if(agingMap.put(key, verCode, captchaAging)==null){
            result.setStatus(new StatusCode(204,"验证码请求频繁，五分钟后再试"));
        }else {
            // 构建返回客户端数据对象
            result.setStatus(new StatusCode(200,"验证码已发送"));
            result.appendData("key", key);
        }

        // 发送邮件
        SendMailDto sendMailDto = new SendMailDto();
        sendMailDto.setTo(email);
        sendMailDto.setContent("您的验证码:"+verCode);
        sendMailDto.setSubject("注册会员");
        mailUtil.sendMail(sendMailDto);

        return result;
    }

    /**
     * 注册账号信息
     *
     * @param admin 用户信息
     * @param key 验证码Key
     * @param captcha 用户输入的验证码
     * @return cn.tworice.common.vo.RequestResult
     * @author 二饭 [2022/5/14 0:05]
     **/
    @PostMapping("reg")
    public RequestResult reg(Admin admin,String key,String captcha){
        RequestResult result = new RequestResult();
        // 判断验证码是否正确
        boolean success=agingMap.exist(key, captcha);
        agingMap.remove(key);
        if(success){
            // 判断该邮箱是否被注册
            Admin admin1=loginService.getAdminByLoginName(admin.getLoginName());
            if(admin1==null){
                // 添加该账号信息到admin表
                boolean success1=loginService.setAdminAndRole(admin,4);
                if(success1){
                    result.setStatus(new StatusCode(200,"注册成功"));
                }else{
                    result.setStatus(new StatusCode(204,"注册异常，请重新尝试"));
                }
            }else{
                result.setStatus(new StatusCode(204,"该账号已经注册过了，请直接登录"));
            }

        }else{
            result.setStatus(new StatusCode(204,"验证码错误"));
        }
        return result;
    }
}
